home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Applications / Eudora 1.3.1 / source / hexbin.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-16  |  17.2 KB  |  711 lines  |  [TEXT/MPS ]

  1. #define FILE_NUM 17
  2. /* Copyright (c) 1990-1992 by the University of Illinois Board of Trustees */
  3. /************************************************************************
  4.  * functions to convert files to binhex and back again
  5.  * much of this code is patterned after xbin by Dave Johnson, Brown University
  6.  * Some is lifted straight from xbin.  Our thanks to Dave & Brown.
  7.  ************************************************************************/
  8. #pragma load EUDORA_LOAD
  9. #pragma segment HexBin
  10.  
  11. /************************************************************************
  12.  * Declarations for private routines
  13.  ************************************************************************/
  14. void HexBinInputChar(Byte c,long estMessageSize);
  15. void HexBinDataChar(short d,long estMessageSize);
  16. int FoundHexBin(void);
  17. int HexBinDecode(Byte c,long estMessageSize);
  18. void AbortHexBin(Boolean error);
  19. void OpenDataFork(void);
  20. int ForkRoll(void);
  21. int FlushBuffer(void);
  22. void ResetHexBin(void);
  23. void comp_q_crc(unsigned short c);
  24. void CrcError(void);
  25.  
  26. /************************************************************************
  27.  * Private globals
  28.  ************************************************************************/
  29. typedef struct
  30. {
  31.     long type;
  32.     long author;
  33.     short flags;
  34.     long dataLength;
  35.     long rzLength;
  36.     unsigned short hCrc;
  37. } HexBinHead;
  38. typedef struct
  39. {
  40.     Str63 flagString;
  41.     short state;
  42.     long oSpot;
  43.     UHandle buffer;
  44.     long bSize;
  45.     long bSpot;
  46.     short refN;
  47.     short vRefN;
  48.     Str63 name;
  49.     Byte lastData;
  50.     Byte state68;
  51.     Byte b8;
  52.     Byte runCount;
  53.     Boolean run;
  54.     long count;
  55.     long size;
  56.     union
  57.     {
  58.         HexBinHead bxHead;
  59.         Byte bxhBytes[sizeof(HexBinHead)];
  60.     } BHHUnion;
  61.     unsigned long calcCrc;
  62.     unsigned long crc;
  63. } HexBinGlobals, *HBGPtr, **HBGHandle;
  64. HexBinGlobals **HBG;
  65. #define State (*HBG)->state
  66. #define OSpot (*HBG)->oSpot
  67. #define Buffer (*HBG)->buffer
  68. #define BSize (*HBG)->bSize
  69. #define BSpot (*HBG)->bSpot
  70. #define RefN (*HBG)->refN
  71. #define VRefN (*HBG)->vRefN
  72. #define Name (*HBG)->name
  73. #define Type (*HBG)->BHHUnion.bxHead.type
  74. #define Author (*HBG)->BHHUnion.bxHead.author
  75. #define Flags (*HBG)->BHHUnion.bxHead.flags
  76. #define RzLength (*HBG)->BHHUnion.bxHead.rzLength
  77. #define DataLength (*HBG)->BHHUnion.bxHead.dataLength
  78. #define HCrc (*HBG)->BHHUnion.bxHead.hCrc
  79. #define BxhBytes (*HBG)->BHHUnion.bxhBytes
  80. #define LastData (*HBG)->lastData
  81. #define State68 (*HBG)->state68
  82. #define B8 (*HBG)->b8
  83. #define RunCount (*HBG)->runCount
  84. #define Run (*HBG)->run
  85. #define Count (*HBG)->count
  86. #define Size (*HBG)->size
  87. #define CalcCrc (*HBG)->calcCrc
  88. #define Crc (*HBG)->crc
  89.  
  90. #define RUNCHAR 0x90
  91.  
  92. #define DONE 0x7F
  93. #define SKIP 0x7E
  94. #define FAIL 0x7D
  95.  
  96. Byte HexBinTable[256] = {
  97. /* 0*/    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  98. /*                            \t   \n                                \r                                */
  99.                 FAIL, SKIP, SKIP, FAIL, FAIL, SKIP, FAIL, FAIL,
  100. /*      ' '                                                                                            */
  101. /* 2*/    SKIP, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  102.                 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  103. /* 4*/    FAIL, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
  104.                 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, FAIL, FAIL,
  105. /* 6*/    0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, FAIL,
  106. /*                                    :                                                                     */
  107.                 0x14, 0x15, DONE, FAIL, FAIL, FAIL, FAIL, FAIL,
  108. /* 8*/    0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
  109.                 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, FAIL,
  110. /*10*/    0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, FAIL,
  111.                 0x2C, 0x2D, 0x2E, 0x2F, FAIL, FAIL, FAIL, FAIL,
  112. /*12*/    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, FAIL,
  113.                 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, FAIL, FAIL,
  114. /*14*/    0x3D, 0x3E, 0x3F, FAIL, FAIL, FAIL, FAIL, FAIL,
  115.                 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  116. /*16*/    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  117.                 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  118.                 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  119.                 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  120.                 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  121.                 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  122.                 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  123.                 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  124.                 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  125.                 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  126.                 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  127.                 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  128.                 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  129.                 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  130.                 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  131.                 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  132. };
  133.     
  134. #pragma segment POP
  135. /************************************************************************
  136.  * SaveHexBin - save a binhex file, if one is found.    Returns the 
  137.  * state of the converter
  138.  ************************************************************************/
  139. short SaveHexBin(UPtr text,long size,long estMessageSize)
  140. {
  141.     if (HBG==nil)
  142.         return(HexDone);        /* if we have no globals, return text unchanged */
  143.     
  144.     if (State==HexDone)
  145.         State = NotHex;         /* start the conversion */
  146.         
  147.     for (Count=0;Count<size;Count++)
  148.         HexBinInputChar(text[Count],estMessageSize);
  149.     
  150.     return(State);
  151. }
  152.  
  153. /************************************************************************
  154.  * EndHexBin - done with a HexBin session
  155.  ************************************************************************/
  156. void EndHexBin(void)
  157. {
  158.     if (HBG)
  159.     {
  160.         if (VRefN && !CommandPeriod) {WarnUser(BINHEX_SHORT,0);BadBinHex=True;}
  161.         AbortHexBin(False);
  162.         DisposHandle(HBG);
  163.         HBG = nil;
  164.     }
  165.     return;
  166. }
  167.  
  168. /************************************************************************
  169.  * BeginHexBin - ready to begin a HexBin session
  170.  ************************************************************************/
  171. void BeginHexBin(void)
  172. {
  173.     HBG = NewH(HexBinGlobals);
  174.     if (HBG)
  175.         WriteZero(*HBG,sizeof(HexBinGlobals));
  176. }
  177. #pragma segment HexBin
  178.  
  179. /************************************************************************
  180.  * HexBinInputChar - read a char from the binhex data, decode it, and
  181.  * let HexBinDataChar do (most of) the rest.
  182.  ************************************************************************/
  183. void HexBinInputChar(Byte c,long estMessageSize)
  184. {
  185.     short d;
  186.  
  187. reSwitch:
  188.     switch (State)
  189.     {
  190.         case HexDone:
  191.             break;
  192.             
  193.         case NotHex:
  194.             if (c==':') State=FoundHexBin();
  195.             break;
  196.  
  197.         case Excess:
  198.             c = HexBinTable[c];
  199.             if (c==DONE)
  200.             {
  201.                 State = HexDone;
  202.                 if (BSpot>3)
  203.                 {
  204.                     WarnUser(BINHEXEXCESS,BSpot-1);
  205.                     BadBinHex = True;
  206.                 }
  207.                 PopProgress(True);
  208.             }
  209.             else if (c!=SKIP)
  210.                 BSpot++;
  211.             break;
  212.     
  213.         case CollectName:
  214.             (*Buffer)[BSpot++] = c;
  215.             /* fall-throught to default */
  216.         default:
  217.             if ((d=HexBinDecode(c,estMessageSize))>=0)
  218.                 HexBinDataChar(d,estMessageSize);
  219.             break;
  220.     }
  221. }
  222.  
  223. /************************************************************************
  224.  * HexBinDataChar - the main engine for the de-binhexer
  225.  * Unfortunately, much of the real work happens as side-effects to functions.
  226.  * State and BSpot are almost always manipulated directly in this routine, but
  227.  * the rest of HBG is up for grabs.
  228.  ************************************************************************/
  229. void HexBinDataChar(short d,long estMessageSize)
  230. {
  231. reSwitch:
  232.     switch (State)
  233.     {
  234.         case CollectName:
  235.             comp_q_crc(d);
  236.             Name[OSpot] = d;
  237.             if (Name[OSpot]==0)
  238.             {
  239.                 State = CollectInfo;
  240.                 BSpot = 0;
  241.                 Name[0] = MIN(Name[0],31);
  242.                 Name[32] = 0;
  243.             }
  244.             else
  245.             {
  246.                 if (++OSpot>sizeof(Name)-2)
  247.                 {
  248.                     WarnUser(BAD_HEXBIN_FORMAT,State);
  249.                     AbortHexBin(True);
  250.                 }
  251.             }
  252.             break;
  253.             
  254.         case CollectInfo:
  255.             BxhBytes[BSpot++] = d;
  256.             switch (sizeof(HexBinHead)-BSpot)
  257.             {
  258.                 case 0:
  259.                     {
  260.                         Str31 name;
  261.                         short vRef;
  262.                         PCopy(name,Name);
  263.                         /*
  264.                          * Note:    The length test can't be 100% correct because of
  265.                          * run-length encoding.  I therefore give it some slop and
  266.                          * hope for the best.  Eudora doesn't produce RLE, and neither
  267.                          * does StuffIt, so perhaps this won't be a problem.  It's
  268.                          * better than the alternative, anyway...
  269.                          */
  270.                         if ((estMessageSize<GetRLong(HEX_SIZE_THRESH) ||
  271.                                 DataLength+RzLength < (estMessageSize*100)/GetRLong(HEX_SIZE_PERCENT)) &&
  272.                                 (AutoWantTheFile(name,&vRef,False) || WantTheFile(name,&vRef)))
  273.                         {
  274.                             VRefN = vRef;
  275.                             PCopy(Name,name);
  276.                             Crc = HCrc;
  277.                             BSpot = 0;
  278.                             CrcError();
  279.                             State = DataWrite;
  280.                             OpenDataFork();
  281.                         }
  282.                         else
  283.                             AbortHexBin(False);
  284.                     }
  285.                     break;
  286.                 case 1:
  287.                     break;
  288.                 default:
  289.                     comp_q_crc(d);
  290.                     break;
  291.             }
  292.             break;
  293.             
  294.         case DataWrite:
  295.         case RzWrite:
  296.             if (OSpot==0)
  297.             {
  298.                 State++;
  299.                 goto reSwitch;
  300.             }
  301.             else
  302.             {
  303.                 (*Buffer)[BSpot++] = d;
  304.                 comp_q_crc(d);
  305.                 OSpot--;
  306.                 if (BSpot==BSize)
  307.                 {
  308.                     if (FlushBuffer()) AbortHexBin(True);
  309.                     BSpot = 0;
  310.                 }
  311.             }
  312.             break;
  313.         case DataCrc1:
  314.         case RzCrc1:
  315.             Crc = d << 8;
  316.             State++;
  317.             break;
  318.         case DataCrc2:
  319.         case RzCrc2:
  320.             State++;
  321.             Crc = Crc | d;
  322.             State = ForkRoll();
  323.             BSpot = 0;
  324.             break;
  325.     }
  326. }
  327.  
  328. /************************************************************************
  329.  * FoundHexBin - the second level of initialization.
  330.  * This function is called when we have detected a HexBin file.  Its
  331.  * major purpose is to allocate a buffer for data
  332.  * If it has allocated a buffer, it continues the HexBin process by
  333.  * returning the next state, CollectHeader; otherwise, it returns HexDone,
  334.  * effectively aborting the HexBin process.
  335.  ************************************************************************/
  336. int FoundHexBin(void)
  337. {
  338.     BSize = GetRLong(BUFFER_SIZE);
  339.     if (!Buffer) Buffer = NuHandle(BSize);
  340.     if (!Buffer)
  341.     {
  342.         WarnUser(BINHEX_MEM,MemError());
  343.         BadBinHex = True;
  344.         return(HexDone);
  345.     }
  346.     else
  347.     {
  348.         ResetHexBin();
  349.         return(CollectName);
  350.     }
  351. }
  352.  
  353. /************************************************************************
  354.  * HexBinDecode - decode a data byte.
  355.  * The binhex data format encodes 3 data bytes into four encoded bytes.
  356.  * There are some "magic" values for encoded bytes:
  357.  *            newline, cr         ignore
  358.  *            :                             end of binhex data
  359.  * There is also a magic data byte, 0x90.  This repeats the PREVIOUS
  360.  * data byte n times, where n is the value of the NEXT data byte.
  361.  * If n is zero, 0x90 itself is output.
  362.  ************************************************************************/
  363. int HexBinDecode(Byte c,long estMessageSize)
  364. {
  365.     Byte b6;
  366.     short data;
  367.         
  368.     if ((b6=HexBinTable[c])>64)
  369.     {
  370.         switch (b6)
  371.         {
  372.             case SKIP:
  373.                 return(-1);
  374.             case DONE:
  375.                 WarnUser(BINHEX_SHORT,0);
  376.                 AbortHexBin(True);
  377.                 return(-1);
  378.             default:
  379.                 if (!PrefIsSet(PREF_HEX_PERMISSIVE))
  380.                 {
  381.                     WarnUser(BINHEX_BADCHAR,c);
  382.                     AbortHexBin(True);
  383.                 }
  384.                 return(-1);
  385.         }
  386.     }
  387.     else
  388.     {
  389.         switch(State68++)
  390.         {
  391.             case 0:
  392.                 B8 = b6<<2;
  393.                 return(-1);
  394.             case 1:
  395.                 data = B8 | (b6 >> 4);
  396.                 B8 = (b6 & 0xf) << 4;
  397.                 break;
  398.             case 2:
  399.                 data = B8 | (b6>>2);
  400.                 B8 = (b6 & 0x3) << 6;
  401.                 break;
  402.             case 3:
  403.                 data = B8 | b6;
  404.                 State68 = 0;
  405.                 break;
  406.         }
  407.         if (!Run)
  408.         {
  409.             if (data == RUNCHAR)
  410.             {
  411.                 Run = 1;
  412.                 RunCount = 0;
  413.                 return(-1);
  414.             }
  415.             else
  416.                 return(LastData = data);
  417.         }
  418.         else
  419.         {
  420.             Run = False;
  421.             if (!data)
  422.                 return(LastData = RUNCHAR);
  423.             while (--data > 0) HexBinDataChar(LastData,estMessageSize);
  424.             return(-1);
  425.         }
  426.     }
  427. }
  428.  
  429.  
  430. /************************************************************************
  431.  * AbortHexBin - something bad has happened.    Get rid of loose ends.
  432.  ************************************************************************/
  433. void AbortHexBin(Boolean error)
  434. {
  435.     if (Buffer) {DisposHandle(Buffer); Buffer=0;}
  436.     if (RefN) {FSClose(RefN); RefN=0;}
  437.     if (VRefN)
  438.     {
  439.         FSDelete(Name,VRefN);
  440.         VRefN = 0;
  441.     }
  442.     State = HexDone;
  443.     BadBinHex = BadBinHex || error;
  444.     PopProgress(True);
  445. }
  446.  
  447. /************************************************************************
  448.  * OpenDataFork - open the data fork of the file
  449.  ************************************************************************/
  450. void OpenDataFork(void)
  451. {
  452.     int err;
  453.     short refN;
  454.     FInfo info;
  455.     
  456.     LDRef(HBG);
  457.     if (err=MakeResFile(Name,VRefN,0,Author,Type))
  458.     {
  459.         FileSystemError(BINHEX_CREATE,Name,err);
  460.         VRefN = 0;
  461.         AbortHexBin(True);
  462.     }
  463.     else if (err=GetFInfo(Name,VRefN,&info))
  464.     {
  465.         FileSystemError(BINHEX_CREATE,Name,err);
  466.         AbortHexBin(True);
  467.     }
  468.     else
  469.     {
  470.         info.fdFlags = Flags;
  471.         info.fdFlags &= ~fOnDesk;
  472.         info.fdFlags &= ~fInvisible;
  473.         info.fdFlags &= ~fInited;
  474.         if (err=SetFInfo(Name,VRefN,&info))
  475.         {
  476.             FileSystemError(BINHEX_OPEN,Name,err);
  477.             AbortHexBin(True);
  478.         }
  479.         else if (err=FSOpen(Name,VRefN,&refN))
  480.         {
  481.             FileSystemError(BINHEX_OPEN,Name,err);
  482.             AbortHexBin(True);
  483.         }
  484.         else
  485.             RefN = refN;
  486.     }
  487.     OSpot = DataLength;
  488.     UL(HBG);
  489. }
  490.  
  491. /************************************************************************
  492.  * ForkRoll - roll from the data fork to the resource fork, or else from
  493.  * the resource fork to cleanup.    Returns the next state.
  494.  ************************************************************************/
  495. int ForkRoll(void)
  496. {
  497.     int err=0;
  498.     short refN;
  499.     long pos;
  500.     
  501.     /*
  502.      * flush and close the current file
  503.      */
  504.     if (RefN)
  505.     {
  506.         CrcError();
  507.         if (err=FlushBuffer())
  508.             AbortHexBin(True);
  509.         else
  510.         {
  511.             if (!GetFPos(RefN,&pos)) SetEOF(RefN,pos);
  512.             if (err=FSClose(RefN))
  513.             {
  514.                 AbortHexBin(True);
  515.                 LDRef(HBG);
  516.                 FileSystemError(BINHEX_WRITE,Name,err);
  517.                 UL(HBG);
  518.             }
  519.         }
  520.     }
  521.     if (err) return(HexDone);
  522.     
  523.     /*
  524.      * open the new one if necessary
  525.      */
  526.     if (State==RzWrite)
  527.     {
  528.         LDRef(HBG);
  529.         if (err=OpenRF(Name,VRefN,&refN))
  530.         {
  531.             FileSystemError(BINHEX_OPEN,Name,err);
  532.             AbortHexBin(True);
  533.         }
  534.         else
  535.             RefN = refN;
  536.         UL(HBG);
  537.         OSpot = RzLength;
  538.         return(err ? HexDone : RzWrite);
  539.     }
  540.     else
  541.     {
  542.         Str31 fileName;
  543.         PCopy(fileName,Name);
  544.         AddAttachNote(VRefN,fileName,Author,Type);
  545.         FlushVol(nil,VRefN);
  546.         VRefN = 0;
  547.         if (Buffer) {DisposHandle(Buffer); Buffer=0;}
  548.         return(Excess);
  549.     }
  550. }
  551.  
  552. /************************************************************************
  553.  * FlushBuffer - write out what we have so far
  554.  ************************************************************************/
  555. int FlushBuffer(void)
  556. {
  557.     long writeBytes = BSpot;
  558.     int err;
  559.     
  560.     if (err=FSWrite(RefN,&writeBytes,LDRef(Buffer)))
  561.         FileSystemError(BINHEX_WRITE,Name,err);
  562.     UL(Buffer);
  563.     BSpot = 0;
  564.     return(err);
  565. }
  566.  
  567. /************************************************************************
  568.  * WantTheFile - see if the user really wants the file
  569.  ************************************************************************/
  570. Boolean WantTheFile(UPtr name,short *vRef)
  571. {
  572.     SFReply sfr;
  573.     Point where;
  574.     Str63 prompt;
  575.     Str63 dfName;
  576.     Str255 message;
  577.     
  578.     MommyMommy(ATTENTION,nil);
  579.     if (InBG) return(AutoWantTheFile(name,vRef,True));
  580.     StdFileSpot(&where,SFPUTFILE_ID);
  581.     GetRString(prompt,BINHEX_PROMPT);
  582.     BlockMove(name,dfName,*name+1);
  583.     PushProgress();
  584.     GetRString(message,BINHEX_HELP);
  585.     Progress(NoChange,message);
  586.     AlertTicks=GetRLong(ALERT_TIMEOUT)*60+TickCount();
  587.     SFPPutFile(where,prompt,dfName,nil,&sfr,SFPUTFILE_ID,DlgFilter);
  588.     AlertTicks = 0;
  589.     if (!sfr.good) return (False);
  590.     BlockMove(sfr.fName,name,*sfr.fName+1);
  591.     *vRef = sfr.vRefNum;
  592.     ComposeRString(message,BINHEX_PROG_FMT,sfr.fName);
  593.     ByteProgress(message,0,4*(RzLength+DataLength)/3);
  594.     return(True); 
  595. }
  596.  
  597. /************************************************************************
  598.  * AutoWantTheFile - see if we can auto-receive the file
  599.  ************************************************************************/
  600. Boolean AutoWantTheFile(UPtr name,short *vRef,Boolean ohYesYouDo)
  601. {
  602.     Str31 dfName;
  603.     long dirId;
  604.     Str31 volName;
  605.     Str63 volPath;
  606.     Str15 iAscii;
  607.     short i,wdRef;
  608.     HFileInfo hfi;
  609.     Str63 message;
  610.     
  611.     if (ohYesYouDo)
  612.     {
  613.         dirId = 2;
  614.         GetMyVolName(MyVRef,volName);
  615.     }
  616.     else
  617.     {
  618.         if (!PrefIsSet(PREF_AUTOHEX)) return(False);
  619.         if (!GetVolpath(GetPref(volPath,PREF_AUTOHEX_VOLPATH),volName,&dirId))
  620.             return(False);
  621.     }
  622.     PCopy(dfName,name);
  623.     SetVol(volName,0);
  624.     wdRef = GetMyWD(0,dirId);
  625.     for (i=1;i<5000 && !HGetFileInfo(wdRef,dirId,dfName,&hfi);i++)
  626.     {
  627.         PCopy(dfName,name);
  628.         *iAscii = 0;
  629.         PLCat(iAscii,i);
  630.         if (*dfName + *iAscii < 31)
  631.             PCat(dfName,iAscii);
  632.         else
  633.         {
  634.             BlockMove(iAscii+1,dfName+32-*iAscii,*iAscii);
  635.             *dfName = 31;
  636.         }
  637.     }
  638.     if (i==5000) return(False);
  639.     PCopy(name,dfName);
  640.     *vRef = wdRef;
  641.     ComposeRString(message,BINHEX_PROG_FMT,dfName);
  642.     ByteProgress(message,0,4*(RzLength+DataLength)/3);
  643.     return(True); 
  644. }
  645.  
  646. /************************************************************************
  647.  * ResetHexBin - ready ourselves for a new HexBin file.
  648.  ************************************************************************/
  649. void ResetHexBin(void)
  650. {
  651.     OSpot = 0;
  652.     BSpot = 0;
  653.     RefN = 0;
  654.     VRefN = 0;
  655.     *Name = 0;
  656.     Crc = 0;
  657.     LastData = 0;
  658.     State68 = 0;
  659.     B8 = 0;
  660.     Run = False;
  661.     CalcCrc = 0;
  662. }
  663.  
  664. /************************************************************************
  665.  * comp_q_crc - lifted from xbin
  666.  ************************************************************************/
  667. #define BYTEMASK 0xff
  668. #define BYTEBIT 0x100
  669. #define WORDMASK 0xffff
  670. #define WORDBIT 0x10000
  671. #define CRCCONSTANT 0x1021
  672.  
  673. void comp_q_crc(unsigned short c)
  674. {
  675.                 register unsigned long temp = CalcCrc;
  676.  
  677. /* Never mind why I call it WOP... */
  678. #define WOP { \
  679.                                 c <<= 1; \
  680.                                 if ((temp <<= 1) & WORDBIT) \
  681.                                                 temp = (temp & WORDMASK) ^ CRCCONSTANT; \
  682.                                 temp ^= (c >> 8); \
  683.                                 c &= BYTEMASK; \
  684.                 }
  685.                 WOP;
  686.                 WOP;
  687.                 WOP;
  688.                 WOP;
  689.                 WOP;
  690.                 WOP;
  691.                 WOP;
  692.                 WOP;
  693.                 CalcCrc = temp;
  694. }
  695.  
  696. /************************************************************************
  697.  * CrcError - does the computed crc (CalcCrc) match the given crc (Crc)
  698.  ************************************************************************/
  699. void CrcError(void)
  700. {
  701.     comp_q_crc(0);
  702.     comp_q_crc(0);
  703.     if ((Crc&WORDMASK) != (CalcCrc&WORDMASK))
  704.     {
  705.         WarnUser(CRC_ERROR,CalcCrc);
  706.         BadBinHex = True;
  707.     }
  708.     CalcCrc = 0;
  709. }
  710.  
  711.